﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace ORM
{
	public static class Helper
	{
		static long lastId = 0;
		static DateTime baseTime = new DateTime(2019, 1, 1);
		readonly static Mutex m = new Mutex();
		/// <summary>
		/// 唯一ID
		/// </summary>
		public static long NewId
		{
			get
			{
				m.WaitOne();
				try
				{
					long seconds = (long)(DateTime.UtcNow - baseTime).TotalSeconds;

					if ((lastId >> 30) != seconds)
						lastId = seconds << 30;
					else
						++lastId;
					return lastId;
				}
				finally
				{
					m.ReleaseMutex();
				}
			}
		}

		/// <summary>
		/// 从NewId生成的id反推对应的时间
		/// </summary>
		/// <param name="id">由NewId生成的id值</param>
		/// <returns>id对应的UTC时间</returns>
		public static DateTime DateTimeFromId(long id) => baseTime.AddSeconds(id >> 30).ToLocalTime();

		/// <summary>
		/// 从时间转换成最小的id
		/// </summary>
		/// <param name="when"></param>
		/// <returns></returns>
		public static long DateTimeToId(DateTime when)
		{
			long seconds = (long)(when.ToUniversalTime() - baseTime).TotalSeconds;
			return seconds << 30;
		}

		/// <summary>
		/// 代替string.Format
		/// </summary>
		/// <param name="str"></param>
		/// <param name="args"></param>
		/// <returns></returns>
		public static string Fmt(this string str, params object[] args) => string.Format(str, args);

		/// <summary>
		/// 代替string.Join
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="glue"></param>
		/// <param name="objs"></param>
		/// <returns></returns>
		public static string JoinBy<T>(this IEnumerable<T> objs, string glue) => string.Join(glue, objs);

		/// <summary>
		/// 代替string.Join
		/// </summary>
		/// <param name="glue"></param>
		/// <param name="objs"></param>
		/// <returns></returns>
		public static string Join(this string glue, params object[] objs) => string.Join(glue, objs);

		/// <summary>
		/// 等同于C#8的obj?.ToArray()
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="obj"></param>
		/// <returns></returns>
		public static T[] toArray<T>(this IEnumerable<T> obj) => obj?.ToArray();

		/// <summary>
		/// 自适应count
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="obj"></param>
		/// <returns></returns>
		public static int count<T>(this IEnumerable<T> obj) => obj == null ? -1 : obj.Count();
	}
}